import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import React, { Component } from 'react';
import
{
    AmbientLight, BoxGeometry, Mesh, MeshLambertMaterial, OrthographicCamera, TextureLoader, MeshBasicMaterial,
    PointLight, Scene, SphereGeometry, WebGLRenderer, ArrowHelper, Vector3, Camera, Raycaster, Vector2, Object3D, RepeatWrapping, PlaneGeometry, PerspectiveCamera, Shape, DoubleSide, ShapeGeometry, MeshPhongMaterial, ExtrudeGeometry
} from 'three';
import tri_pattern from '../../assets/img/tri_pattern.jpg';
import hot from '../../assets/img/hot.png';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';//直接引用包里面的
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import { Color } from 'three';
import origin from '../../assets/img/origin.webp';
import pic from '../../assets/img/level.webp';
import sofapic from '../../assets/img/sofa.png';
@observer
export default class Contour extends Component
{
    @observable myDemo = document.getElementById("myScene") as HTMLDivElement;
    @observable scene = new Scene(); //场景:就是图形渲染的画布
    // @observable camera = new OrthographicCamera( //相机:就是你观察的视角,相机的选择决定了相机的操作
    //     -150 * (this.myDemo.offsetWidth / this.myDemo.offsetHeight), //视野角度
    //     150 * (this.myDemo.offsetWidth / this.myDemo.offsetHeight), //长宽比
    //     150,
    //     -150,
    //     1, //近截面
    //     1000 //远截面 超出远截面或小于近截面就不渲染
    // );
    @observable camera = new PerspectiveCamera(
        75, //视野角度
        this.myDemo.offsetWidth / this.myDemo.offsetHeight, //长宽比
        0.1, //近截面
        1000 //远截面 超出远截面或小于近截面就不渲染
    );
    @observable renderer = new WebGLRenderer(); //渲染器:建立好了模型需要用渲染器渲染
    @observable geometryCube = new BoxGeometry(100, 200, 10); //几何图形:建一个什么样的形状,这是一个正方体
    @observable geometrySphere = new SphereGeometry(40, 40, 40); //这是一个球体
    @observable material = new MeshLambertMaterial({ //材质的选择决定是否受光照影响
        color: 0x13c2c2
    }); //材质对象Material:渲染出个什么样的物体
    @observable pointLight = new PointLight(0xffffff);//点光源
    @observable ambient = new AmbientLight(0x444444);//环境光
    @observable control = new OrbitControls(this.camera, this.renderer.domElement);//控制相机到处看

    //三根辅助箭头
    @observable arrowHelperY = new ArrowHelper(new Vector3(0, 1, 0), new Vector3(0, 0, 0), 250, 0x00ff00);
    @observable arrowHelperX = new ArrowHelper(new Vector3(1, 0, 0), new Vector3(0, 0, 0), 250, 0xff0000);
    @observable arrowHelperZ = new ArrowHelper(new Vector3(0, 0, 1), new Vector3(0, 0, 0), 250, 0x0000ff);
    @observable poiOb: Object3D[] = []; //所有模型的位置
    @observable poiObBorder: Object3D[] = [];
    @action setScene = (scene: Scene, camera: Camera, renderer: WebGLRenderer) =>
    {
        //设置箭头坐标
        scene.add(this.arrowHelperY);
        scene.add(this.arrowHelperX);
        scene.add(this.arrowHelperZ);


        this.pointLight.position.set(-400, 200, -300); //设置点光源位置

        scene.add(this.pointLight); //添加点光源
        scene.add(this.ambient); //添加环境光

        renderer.setSize(this.myDemo.offsetWidth, this.myDemo.offsetHeight);
        this.myDemo.appendChild(this.renderer.domElement);

        camera.position.set(0, 0, 500);
        camera.lookAt(scene.position);
    };
    @action
    renderCube = () =>
    {
        let background = new Mesh(new PlaneGeometry(580, 453), new MeshBasicMaterial({ map: new TextureLoader().load(origin, (texture) => { this.myRender(); }) }));
        let plane = new Mesh(new PlaneGeometry(125, 169), new MeshBasicMaterial({ map: new TextureLoader().load(pic, () => { this.myRender(); }) }));
        plane.userData = { message: "我是挂画" };
        let sofa = new Mesh(new PlaneGeometry(285, 150), new MeshBasicMaterial({ map: new TextureLoader().load(sofapic, (texture) => { this.myRender(); }) }));
        let sofaShape = new Shape();
        sofaShape.moveTo(0, 0);
        sofaShape.lineTo(0, 1.4);
        sofaShape.lineTo(2, 1.4);
        sofaShape.lineTo(2, 0);


        let planeGeometry = new ShapeGeometry(sofaShape);
        let planeMaterial = new MeshPhongMaterial({ color: 0x0FB4DD, side: DoubleSide, depthTest: true });
        const planeG = new Mesh(planeGeometry, planeMaterial);

        background.position.set(0, 0, 0);
        plane.position.set(-190, 30, 1);
        sofa.position.set(-150, -100, 2);
        planeG.position.set(-280, -160, 20);
        planeG.scale.set(50, 50, 50);


        // this.cube.position.set(0, 120, 120);
        this.scene.add(background);
        this.scene.add(plane);
        this.scene.add(sofa);
        // this.scene.add(planeG);


        // this.poiOb.push(background);
        this.poiOb.push(plane);
        // this.poiOb.push(sofa);
        this.poiOb.push(planeG);


        this.setScene(this.scene, this.camera, this.renderer);

        this.myRender();
    };
    @action
    myRender = () =>
    {
        // this.renderer.render(this.scene, this.camera);
        this.composer.render();
    };
    raycast = (e: MouseEvent) =>
    {
        let canvas = e.target as HTMLCanvasElement;
        e.preventDefault();

        let raycaster = new Raycaster();
        let mouse = new Vector2();
        //将鼠标点击位置的屏幕坐标转成threejs中的标准坐标
        mouse.x = ((e.clientX - 256) / canvas.clientWidth) * 2 - 1;
        mouse.y = -(e.clientY / canvas.clientHeight) * 2 + 1;

        raycaster.setFromCamera(mouse, this.camera);
        let intersect = raycaster.intersectObjects(this.poiOb);
        if (intersect.length > 0)
        {
            this.poiObBorder = [];
            this.poiObBorder.push(intersect[0].object);
            this.outlinepass.selectedObjects = this.poiObBorder;
            this.myRender();
            console.log(intersect);
        }
        else
        {
            this.outlinepass.selectedObjects = [];
            this.myRender();
        }

    };
    @observable composer = new EffectComposer(this.renderer);
    @observable outlinepass = new OutlinePass(new Vector2(this.myDemo.offsetWidth, this.myDemo.offsetHeight), this.scene, this.camera);

    setUpComposer() //初始化效果编辑器
    {
        this.composer.setSize(this.myDemo.offsetWidth, this.myDemo.offsetHeight);

        this.outlinepass.visibleEdgeColor = new Color('#ffec3d');
        this.outlinepass.hiddenEdgeColor = new Color('#ff0000');
        this.outlinepass.setSize(30, 30);

        let renderpass = new RenderPass(this.scene, this.camera);
        this.composer.addPass(renderpass);
        this.composer.addPass(this.outlinepass);

        const textureLoader = new TextureLoader();
        textureLoader.load(tri_pattern, (texture) =>
        {
            this.outlinepass.patternTexture = texture;
            texture.wrapS = RepeatWrapping;
            texture.wrapT = RepeatWrapping;
        });

        let effectFXAA = new ShaderPass(FXAAShader);
        effectFXAA.uniforms['resolution'].value.set(   //设置分辨率
            1 / this.myDemo.offsetWidth, 1 / this.myDemo.offsetHeight
        );
        this.composer.addPass(effectFXAA);
        window.addEventListener('resize', () =>
        {
            console.log("im resize");
            const width = this.myDemo.offsetWidth;
            const height = this.myDemo.offsetHeight;

            this.camera.aspect = width / height;
            this.camera.updateProjectionMatrix();

            this.renderer.setSize(width, height);
            this.composer.setSize(width, height);
            effectFXAA.uniforms['resolution'].value.set(
                1 / this.myDemo.offsetWidth, 1 / this.myDemo.offsetHeight
            );
        });

        this.renderer.domElement.addEventListener('mousemove', (e) => { this.raycast(e); });
    }

    componentDidMount() //等待我DIV出来
    {
        this.setUpComposer();
        this.renderer.setClearColor(0x00000, 1);

        this.renderCube();

        this.control.enablePan = false; //禁止拖拽 改变原点位置
        this.control.enableDamping = true;//轨道控制 是否有惯性 阻尼。。。
        this.control.dampingFactor = .5; //阻尼数值
        this.control.addEventListener('change', this.myRender);

    }
    render()
    {
        return (
            <div id="myScene" style={{ width: "100%", height: "100%" }} >

            </ div>
        );
    }
}
